Amazon Aurora ServerlessでHTTPSエンドポイントができ本当にサーバーレスアーキテクチャで利用可能になる!
大栗です。
Aurora Serverlessは発表時にServerlessアーキテクチャ用のRDBMSが出た!と勘違いされることが多くありました。今回Data APIというHTTPSのエンドポイントができました。これによりLambdaなどからの接続が行いやすくなります!
- Announcement: Access your Amazon Aurora Serverless Database with the New Data API (Beta)
- Using the Data API for Aurora Serverless
Data API for Aurora Serverless (Beta)
今までLambdaからAurora Serverlessへアクセスするためには、以下の2通りがありました。
- Auroraをパブリック接続可能にする
- LambdaをVPCアクセス可能にする
Auroraをパブリック接続可能にする
場合は、Auroraがインターネットに面しているのでセキュリティに問題があります。通常のログインを禁止にしてIAM認証を有効化することも可能ですが、1秒あたり20接続しか行えないなどの制限があります。LambdaをVPCアクセス可能にする
場合には、コンテナの初期起動時にENIを作成するため起動が遅くなったり、VPC内のIPアドレスが枯渇するという問題の可能性がありました。
またLambdaを使用するとコネクションプールが使用しづらいためRDBMSへの接続数が膨大になってしまう恐れがあります。
つまりLambdaとRDBMSは相性が悪いと言われていました。しかし、今回利用できる様になったData APIはそれらの問題点を払拭できる可能性があります。
VPC経由でLambdaからAurora Serverlessへアクセスする場合は以下のようにLambdaのコンテナごとにENIを作成していました。
Data APIを利用するとLambdaからData APIにアクセスするので、ENIを作成しません。そのためENIの作成時間やIPアドレスの枯渇が発生しません。Data APIのエンドポイントでコネクションのプーリングや流量制御をしてくれると助かるのですが、どの様な動作になるのか確認できていません。
このData APIはAppSyncからも利用可能になっています。
AuroraのIAM認証と何が違うの?
類似の機能としてIAM認証があるため比較してみました
Aurora Serverless Data API | Aurora IAM認証 | |
---|---|---|
接続数 | 接続数制限の規定無し | 1秒あたり20接続 |
トランザクション | 無し | 有り |
コネクション | リクエスト毎で分かれる | 永続的 |
接続方法 | HTTPS | MySQLプロトコル |
対象DB | Aurora Serverless | Aurora MySQL, Aurora PostgreSQL, MySQL, PostgreSQL |
アクセス先 | 専用のパブリックなエンドポイントへアクセス | DBに直接ログイン |
※: 本表は現在確認できる情報から筆者が独自に作成しています。
注意
- Aurora ServerlessのData APIは現在Beta版のため、変更される可能性があります。
- Data APIではトランザクションはサポートされません。
- レスポンスは最大1,000行で1MBのサイズ制限があります。
- 現在利用可能なリージョンは米国東部 (バージニア北部)のみです。
- コネクションは最大1分でタイムアウトします。
- 認証情報はSecrets Managerを使ってDBに接続します。
やってみた
事前設定
以下の状態を前提とします。
- リージョン: 米国東部 (バージニア北部)
- Auroraエンジン: Aurora Serverless 5.6.10a
まず、Aurora Serverlessを起動します。Aurora Serverlessの起動方法は以下のエントリを御覧ください。
Aurora Serverlessの起動が完了したら、クラスタの変更を行いData APIを有効化します。
対象のクラスタを選択してクラスターの変更
をクリックします。
ネットワーク & セキュリティ
にWeb Service Data API - Beta
という項目が増えているので、Data API
をチェックします。
ここではすぐに適用
を選択してクラスターの変更
を実行します。
これでData APIが有効になりました。
実行してみる
まず単純なselect now();
というクエリをAWS CLIから実行してみます。AWS CLIではaws rds-data execute-sql
というコマンドを使用します。
$ aws rds-data execute-sql \ > --aws-secret-store-arn arn:aws:secretsmanager:us-east-1:123456789012:secret:aurora/serverless/data-api-a1b2c3 \ > --db-cluster-or-instance-arn arn:aws:rds:us-east-1:123456789012:cluster:serverless \ > --sql-statements "select now();" \ > --region us-east-1 { "sqlStatementResults": [ { "numberOfRecordsUpdated": -1, "resultFrame": { "records": [ { "values": [ { "stringValue": "2018-11-21 04:37:56.0" } ] } ], "resultSetMetadata": { "columnCount": 1, "columnMetadata": [ { "isAutoIncrement": false, "name": "now()", "nullable": 0, "isCurrency": false, "precision": 19, "arrayBaseColumnType": 0, "label": "now()", "typeName": "DATETIME", "scale": 0, "isCaseSensitive": false, "isSigned": false, "schemaName": "", "type": 93 } ] } } } ] }
上記のようにデータは配列の配列としてレコードが返されます。
次にデータベースとテーブルを作成してみます。
まずデータベースmydb
を作成します。
$ aws rds-data execute-sql \ > --aws-secret-store-arn arn:aws:secretsmanager:us-east-1:123456789012:secret:aurora/serverless/data-api-a1b2c3 \ > --db-cluster-or-instance-arn arn:aws:rds:us-east-1:123456789012:cluster:serverless \ > --sql-statements "create database mydb" \ > --region us-east-1 { "sqlStatementResults": [ { "numberOfRecordsUpdated": 1 } ] }
次にテーブルsample_table
を作成します。
$ aws rds-data execute-sql \ > --aws-secret-store-arn arn:aws:secretsmanager:us-east-1:123456789012:secret:aurora/serverless/data-api-a1b2c3 \ > --database mydb \ > --db-cluster-or-instance-arn arn:aws:rds:us-east-1:123456789012:cluster:serverless \ > --sql-statements "create table sample_table (col1 int, col2 varchar(20), col3 datetime);" \ > --region us-east-1 { "sqlStatementResults": [ { "numberOfRecordsUpdated": 0 } ] }
1件データも挿入してみます。
$ aws rds-data execute-sql \ > --aws-secret-store-arn arn:aws:secretsmanager:us-east-1:123456789012:secret:aurora/serverless/data-api-a1b2c3 \ > --database mydb \ > --db-cluster-or-instance-arn arn:aws:rds:us-east-1:123456789012:cluster:serverless \ > --sql-statements "insert into sample_table (col1, col2, col3 ) VALUES (1, 'Aurora Serverless', now());" \ > --region us-east-1 { "sqlStatementResults": [ { "numberOfRecordsUpdated": 1 } ] }
ちゃんとデータも確認できます。
$ aws rds-data execute-sql \ > --aws-secret-store-arn arn:aws:secretsmanager:us-east-1:123456789012:secret:aurora/serverless/data-api-a1b2c3 \ > --database mydb \ > --db-cluster-or-instance-arn arn:aws:rds:us-east-1:123456789012:cluster:serverless \ > --sql-statements "select * from sample_table;" \ > --region us-east-1 { "sqlStatementResults": [ { "numberOfRecordsUpdated": -1, "resultFrame": { "records": [ { "values": [ { "intValue": 1 }, { "stringValue": "Aurora Serverless" }, { "stringValue": "2018-11-21 05:26:57.0" } ] } ], "resultSetMetadata": { "columnCount": 3, "columnMetadata": [ { "isAutoIncrement": false, "name": "col1", "nullable": 1, "tableName": "sample_table", "isCurrency": false, "precision": 11, "arrayBaseColumnType": 0, "label": "col1", "typeName": "INT", "scale": 0, "isCaseSensitive": false, "isSigned": true, "schemaName": "", "type": 4 }, { "isAutoIncrement": false, "name": "col2", "nullable": 1, "tableName": "sample_table", "isCurrency": false, "precision": 20, "arrayBaseColumnType": 0, "label": "col2", "typeName": "VARCHAR", "scale": 0, "isCaseSensitive": false, "isSigned": false, "schemaName": "", "type": 12 }, { "isAutoIncrement": false, "name": "col3", "nullable": 1, "tableName": "sample_table", "isCurrency": false, "precision": 19, "arrayBaseColumnType": 0, "label": "col3", "typeName": "DATETIME", "scale": 0, "isCaseSensitive": false, "isSigned": false, "schemaName": "", "type": 93 } ] } } } ] }
Lambdaからアクセスしてみる
以下の環境でLambdaを作成します。
- リージョン: 米国東部 (バージニア北部)
- ランタイム: Python 3.7
- Lambda実行のIAM権限: AmazonRDSDataFullAccessポリシーを設定
以下のコードでLambda関数を作成します。Data APIを使用するにはboto3でRDSDataServiceを使用します。
import json import pprint import boto3 def lambda_handler(event, context): client = boto3.client('rds-data') response = client.execute_sql( awsSecretStoreArn='arn:aws:secretsmanager:us-east-1:123456789012:secret:aurora/serverless/data-api-hsbd0Q', database='mydb', dbClusterOrInstanceArn='arn:aws:rds:us-east-1:123456789012:cluster:serverless', sqlStatements='select * from sample_table;' ) pprint.pprint(response) # TODO implement return { 'statusCode': 200, 'body': json.dumps('Hello Aurora Serverles Data API !') }
適当なテストイベントを設定してテスト実行してみます。すると以下のようなエラーが発生しました。2018年11月21日現在ではLambdaのSDKでrds-data
サービスにまだ対応していないようです。早くSDKのバージョンが上がりrds-data
に対応してほしいです。
{ "errorMessage": "Unknown service: 'rds-data'. Valid service names are: acm, acm-pca, alexaforbusiness, apigateway, application-autoscaling, appstream, appsync, athena, autoscaling, autoscaling-plans, batch, budgets, ce, chime, cloud9, clouddirectory, cloudformation, cloudfront, cloudhsm, cloudhsmv2, cloudsearch, cloudsearchdomain, cloudtrail, cloudwatch, codebuild, codecommit, codedeploy, codepipeline, codestar, cognito-identity, cognito-idp, cognito-sync, comprehend, config, connect, cur, datapipeline, dax, devicefarm, directconnect, discovery, dlm, dms, ds, dynamodb, dynamodbstreams, ec2, ecr, ecs, efs, eks, elasticache, elasticbeanstalk, elastictranscoder, elb, elbv2, emr, es, events, firehose, fms, gamelift, glacier, glue, greengrass, guardduty, health, iam, importexport, inspector, iot, iot-data, iot-jobs-data, iot1click-devices, iot1click-projects, iotanalytics, kinesis, kinesis-video-archived-media, kinesis-video-media, kinesisanalytics, kinesisvideo, kms, lambda, lex-models, lex-runtime, lightsail, logs, machinelearning, macie, marketplace-entitlement, marketplacecommerceanalytics, mediaconvert, medialive, mediapackage, mediastore, mediastore-data, mediatailor, meteringmarketplace, mgh, mobile, mq, mturk, neptune, opsworks, opsworkscm, organizations, pi, pinpoint, pinpoint-email, polly, pricing, rds, redshift, rekognition, resource-groups, resourcegroupstaggingapi, route53, route53domains, s3, sagemaker, sagemaker-runtime, sdb, secretsmanager, serverlessrepo, servicecatalog, servicediscovery, ses, shield, signer, sms, snowball, sns, sqs, ssm, stepfunctions, storagegateway, sts, support, swf, transcribe, translate, waf, waf-regional, workdocs, workmail, workspaces, xray", "errorType": "UnknownServiceError", "stackTrace": [ " File \"/var/task/lambda_function.py\", line 7, in lambda_handler\n client = boto3.client('rds-data')\n", " File \"/var/runtime/boto3/__init__.py\", line 91, in client\n return _get_default_session().client(*args, **kwargs)\n", " File \"/var/runtime/boto3/session.py\", line 263, in client\n aws_session_token=aws_session_token, config=config)\n", " File \"/var/runtime/botocore/session.py\", line 809, in create_client\n client_config=config, api_version=api_version)\n", " File \"/var/runtime/botocore/client.py\", line 69, in create_client\n service_model = self._load_service_model(service_name, api_version)\n", " File \"/var/runtime/botocore/client.py\", line 104, in _load_service_model\n api_version=api_version)\n", " File \"/var/runtime/botocore/loaders.py\", line 132, in _wrapper\n data = func(self, *args, **kwargs)\n", " File \"/var/runtime/botocore/loaders.py\", line 378, in load_service_model\n known_service_names=', '.join(sorted(known_services)))\n" ] }
さいごに
今までLambdaからRDBMSにアクセスする構成は高負荷でない場面などに限られおり、。そのためサーバーレスアーキテクチャの中でデータストアに対して複雑なクエリを発行するのが難しく、アプリ作成の難易度が上がる場合がしばしばありました。今回のアップデートによりサーバーレスアーキテクチャでもRDBMSがデータストアとして選択肢に上ってきたと思います。